/**!
 *
 * jQuery 工具类。
 *
 */

(function ($) {
    /**
     *
     * 对象为空。
     *
     * @param o 对象
     * @returns {Boolean} 是否为空：
     * <ol>
     *    <li>true-为空；</li>
     *    <li>false-不为空。</li>
     * </ol>
     *
     */
    $.isNull = function (o) {
        try {
            if (($.type(o) === "undefined") || (o == null)) {
                return true;
            }

            return false;
        } catch (e) {
            return true;
        }
    };

    /**
     *
     * 对象不为空。
     *
     * @param o 对象
     * @returns {Boolean} 是否为空：
     * <ol>
     *    <li>true-不为空；</li>
     *    <li>false-为空。</li>
     * </ol>
     *
     */
    $.isNotNull = function (o) {
        return !$.isNull(o);
    };

    /**
     *
     * 字符串为空。
     *
     * @param str 字符串
     * @returns {Boolean} 是否为空：
     * <ol>
     *    <li>true-为空；</li>
     *    <li>false-不为空。</li>
     * </ol>
     *
     */
    $.isBlank = function (str) {
        try {
            if (($.type(str) === "undefined") || (str == null)) {
                return true;
            } else if (($.type(str) === "number") || ($.type(str) === "boolean")) {
                return false;
            } else if ($.type(str) === "string") {
                if ($.trim(str).length === 0) {
                    return true;
                } else {
                    return false;
                }
            }

            return true;
        } catch (e) {
            return true;
        }
    };

    /**
     *
     * 字符串不为空。
     *
     * @param str 字符串
     * @returns {Boolean} 是否为空：
     * <ol>
     *    <li>true-不为空；</li>
     *    <li>false-为空。</li>
     * </ol>
     *
     */
    $.isNotBlank = function (str) {
        return !$.isBlank(str);
    };

    /**
     *
     * 判断变量 v 是否存在。
     *
     * @param v 变量
     * @returns {Boolean} 是否存在：
     * <ol>
     *    <li>true-存在；</li>
     *    <li>false-不存在。</li>
     * </ol>
     *
     */
    $.isVarExists = function (v) {
        try {
            if ($.type(v) === "undefined") {
                return false;
            }

            return true;
        } catch (e) {
            return false;
        }
    };

    /**
     *
     * 判断非空变量是否为原生对象。
     *
     * @param o 变量
     * @returns {Boolean} 是否为原生对象：
     * <ol>
     *    <li>true-是；</li>
     *    <li>false-否。</li>
     * </ol>
     *
     */
    $.isObject = function (o) {
        try {
            return $.isPlainObject(o);
        } catch (e) {
            return false;
        }
    };

    /**
     *
     * 判断非空变量是否为 jQuery 对象。
     *
     * @param o 变量
     * @returns {Boolean} 是否为 jQuery 对象：
     * <ol>
     *    <li>true-是；</li>
     *    <li>false-否。</li>
     * </ol>
     *
     */
    $.is_jQueryObj = function (o) {
        try {
            return ($.isNotNull(o) && $.isNotBlank(o.jquery) && (o.length > 0));
        } catch (e) {
            return false;
        }
    };

    /**
     *
     * 判断变量是否为数字。
     *
     * @param o 变量
     * @returns {Boolean} 是否为数字：
     * <ol>
     *    <li>true-是；</li>
     *    <li>false-否。</li>
     * </ol>
     *
     */
    $.isNumber = function (o) {
        try {
            return $.isNumeric(o);
        } catch (e) {
            return false;
        }
    };

    /**
     *
     * 判断变量是否为布尔值。
     *
     * @param o 变量
     * @returns {Boolean} 是否为布尔值：
     * <ol>
     *    <li>true-是；</li>
     *    <li>false-否。</li>
     * </ol>
     *
     */
    $.isBoolean = function (o) {
        try {
            if ($.type(o) === "boolean") {
                return true;
            }

            return false;
        } catch (e) {
            return false;
        }
    };

    /**
     *
     * 检查邮箱格式是否正确。
     *
     * @param mail 邮箱
     * @returns {Boolean} 格式是否正确：
     * <ol>
     *    <li>true-正确；</li>
     *    <li>false-错误。</li>
     * </ol>
     *
     */
    $.checkMail = function (mail) {
        if ($.isNotBlank(mail)) {
            if ((mail.length >= 5) && (mail.length <= 30)) {
                return mailRE.test(mail);
            }
        }

        return false;
    };

    /**
     *
     * 显示等待模态框。
     *
     * @param options 参数
     * <ol>
     *    <li>modal：true-显示；false-不显示；</li>
     *    <li>loadMsg：等待信息。</li>
     * </ol>
     *
     */
    $.showLoadModal = function (options) {
        // 是否显示等待模态框，true-显示；false-不显示，默认：不显示
        options.modal = (($.type(options.modal) === "boolean") ? options.modal : false);
        // 加载信息
        options.loadMsg = ($.isBlank(options.loadMsg) ? "" : (options.loadMsg + "…"));

        var $loadModal = $("#load-modal");

        // 显示等待模态框
        if (options.modal) {
            $loadModal.find("span.load-msg").html(options.loadMsg);
            $loadModal.css("display", "block");

            // 隐藏等待模态框
        } else {
            $loadModal.find("span.load-msg").html("");
            $loadModal.css("display", "none");
        }
    };

    /**
     *
     * 显示提示信息模态框。
     *
     * @param tipsMsg 提示信息
     *
     */
    $.showTipsMsgModal = function (tipsMsg) {
        var $tipsMsgModal = $("#tips-msg-modal");

        if ($.isBlank(tipsMsg)) {
            tipsMsg = "暂无提示信息！";
        }

        $tipsMsgModal.find("p").html(tipsMsg);
        $tipsMsgModal.modal("show");
    };

    /**
     *
     * 显示确认模态框。
     *
     * @param options 配置
     *
     */
    $.showConfirmModal = function (options) {
        // 修正参数
        options.msg = ($.isBlank(options.msg) ? "确认吗？" : options.msg);

        var $confirmModal = $("#confirm-modal");

        $confirmModal.find("p").html(options.msg);
        $confirmModal.modal("show");

        if ($.isFunction(options.confirmFn)) {
            $("#confirm-btn").unbind("click");

            $("#confirm-btn").click(function () {
                $confirmModal.modal("hide");

                options.confirmFn();
            });
        }
    };

    /**
     *
     * 字符串换行处理。
     *
     * @param str 字符串
     * @param splitCount 每隔多个字符
     * @return {string} 换行后的字符串
     *
     */
    $.newlineStr = function (str, splitCount) {
        // 换行后的字符串
        var newlineStr = "";

        if ($.isBlank(str) || !$.isNumber(splitCount)) {
            return "";
        }

        splitCount = Number(splitCount);

        if ((splitCount <= 0) || (str.length <= splitCount)) {
            return str;
        } else {
            var split = (str.length / splitCount);

            for (var i = 0; i < split; i++) {
                if (i === 0) {
                    newlineStr += str.substring((i * splitCount), ((i + 1) * splitCount));
                } else {
                    newlineStr += ("\n" + str.substring((i * splitCount), ((i + 1) * splitCount)));
                }
            }

            // 非整除
            if ((str.length % splitCount) !== 0) {
                newlineStr += ("\n" + str.substring((split * splitCount)));
            }
        }

        return newlineStr;
    };

    /**
     *
     * 中文字符串换行处理。
     *
     * @param chineseStr 中文字符串
     * @param splitCount 每隔多个中文换行
     * @return {string} 换行后的中文字符串，如果包含非中文字符串，将返回空串
     *
     */
    $.newlineChineseStr = function (chineseStr, splitCount) {
        // 中文的正则表达式
        var chineseRE = /^[\u4e00-\u9fa5]+$/i;

        if ($.isBlank(chineseStr) || !chineseRE.test(chineseStr)) {
            return "";
        }

        return $.newlineStr(chineseStr, splitCount);
    };

    /**
     *
     * 数组求和。
     *
     * @param arr 数字数组
     * @return {number} 和
     *
     */
    $.sumArray = function (arr) {
        var sum = 0;

        if ($.isArray(arr)) {
            $.each(arr, function (i, e) {
                if ($.isNumber(e)) {
                    sum += Number(e);
                }
            });
        }

        return sum;
    };

    /**
     *
     * 给对象数组中对象的某个字段求和。
     *
     * @param objArr 对象数组
     * @param objField 对象字段
     * @return {number} 和
     *
     */
    $.sumObjArray = function (objArr, objField) {
        var sum = 0;

        if ($.isArray(objArr) && $.isNotBlank(objField) && !$.isNumber(objField)) {
            $.each(objArr, function (i, e) {
                if ($.isObject(e)) {
                    var value = e[objField];

                    if ($.isNumber(value)) {
                        sum += Number(value);
                    }
                }
            });
        }

        return sum;
    };

    /**
     *
     * 判断 str 是否以 startsStr 开始。
     *
     * @param str 字符串
     * @param startsStr 开始的字符串
     * @return {boolean}
     * <ol>
     *    <li>true-是；</li>
     *    <li>false-否。</li>
     * </ol>
     *
     */
    $.startsWithStr = function (str, startsStr) {
        if ($.isBlank(str) || $.isBlank(startsStr)) {
            return false;
        }

        if (str.indexOf(startsStr) === 0) {
            return true
        } else {
            return false;
        }
    };

    /**
     *
     * 判断 str 是否以 endsStr 结束。
     *
     * @param str 字符串
     * @param endsStr 结束的字符串
     * @return {boolean}
     * <ol>
     *    <li>true-是；</li>
     *    <li>false-否。</li>
     * </ol>
     *
     */
    $.endsWithStr = function (str, endsStr) {
        if ($.isBlank(str) || $.isBlank(endsStr)) {
            return false;
        }

        if ((str.lastIndexOf(endsStr) + endsStr.length) === str.length) {
            return true
        } else {
            return false;
        }
    };

    /**
     *
     * 给基本类型数组排序。
     *
     * @param arr 数组
     * @param sortBy 排序方式：
     * <ol>
     *    <li>asc-升序；</li>
     *    <li>desc-降序。</li>
     * </ol>
     *
     * @return {*|Array.<T>} 排序后的数组
     *
     */
    $.sortArray = function (arr, sortBy) {
        if (!$.isArray(arr)) {
            return new Array();
        }

        if ($.isBlank(sortBy)) {
            return arr;
        }

        sortBy = String(sortBy).toLowerCase();

        if (("asc" !== sortBy) && ("desc" !== sortBy)) {
            return arr;
        }

        // 比较器
        var compare = function (v1, v2) {
            // v1 和 v2 其中一个为空，禁止排序
            if ($.isBlank(v1) || $.isBlank(v2)) {
                return 0;
            }

            // 升序
            if (sortBy === "asc") {
                if (v1 > v2) {
                    return 1;
                } else if (v1 < v2) {
                    return -1;
                } else {
                    return 0;
                }

                // 降序
            } else if (sortBy === "desc") {
                if (v1 > v2) {
                    return -1;
                } else if (v1 < v2) {
                    return 1;
                } else {
                    return 0;
                }

                // 什么玩意？
            } else {
                return 0;
            }
        }

        return arr.sort(compare);
    };

    /**
     *
     * 给对象数组排序。
     *
     * @param objArr 对象数组
     * @param sortField 排序字段
     * @param sortBy 排序方式：
     * <ol>
     *    <li>asc-升序；</li>
     *    <li>desc-降序。</li>
     * </ol>
     *
     * @return {*|Array.<T>} 排序后的数组
     *
     */
    $.sortObjArray = function (objArr, sortField, sortBy) {
        if (!$.isArray(objArr)) {
            return new Array();
        }

        if ($.isBlank(sortField) || $.isNumber(sortField) || $.isBlank(sortBy)) {
            return objArr;
        }

        sortField = String(sortField);
        sortBy = String(sortBy).toLowerCase();

        if (("asc" !== sortBy) && ("desc" !== sortBy)) {
            return objArr;
        }

        // 比较器
        var compare = function (o1, o2) {
            // o1 和 o2 其中一个不为对象，禁止排序
            if (!$.isObject(o1) || !$.isObject(o2)) {
                return 0;
            }

            var v1 = ($.isNumber(o1[sortField]) ? Number(o1[sortField]) : 0);
            var v2 = ($.isNumber(o2[sortField]) ? Number(o2[sortField]) : 0);

            // 升序
            if (sortBy === "asc") {
                if (v1 > v2) {
                    return 1;
                } else if (v1 < v2) {
                    return -1;
                } else {
                    return 0;
                }

                // 降序
            } else if (sortBy === "desc") {
                if (v1 > v2) {
                    return -1;
                } else if (v1 < v2) {
                    return 1;
                } else {
                    return 0;
                }

                // 什么玩意？
            } else {
                return 0;
            }
        }

        return objArr.sort(compare);
    };

    /**
     *
     * 根据 fieldKey 在 field 上从 objArr 中查找对象。
     *
     * @param objArr 对象数组
     * @param field 字段
     * @param fieldKey 字段键，即查找对象的字段值，在 objArr 中需要保证它是唯一的才有意义
     * @return {Object} key 对应的对象
     *
     */
    $.getObjFromObjArr = function (objArr, field, fieldKey) {
        var obj = null;

        if ($.isArray(objArr) && $.isNotBlank(field) && !$.isNumber(field) && $.isNotBlank(fieldKey)) {
            $.each(objArr, function (i, e) {
                if ($.isObject(e)) {
                    if (e[field] == fieldKey) {
                        obj = e;

                        // 终止循环
                        return false;
                    }
                }
            });
        }

        return obj;
    };

    /**
     *
     * 获取安全的字符串。
     *
     * @param str 字符串
     * @return {string} 安全的字符串
     *
     */
    $.getString = function (str) {
        return ($.isBlank(str) ? "" : String(str));
    };

    /**
     *
     * 获取安全的数字。
     *
     * @param num 数字
     * @return {number} 安全的数字
     *
     */
    $.getNumber = function (num) {
        return ($.isNumber(num) ? Number(num) : 0);
    };

    /**
     *
     * 获取安全的布尔。
     *
     * @param bl 布尔
     * @return {boolean} 安全的布尔
     *
     */
    $.getBoolean = function (bl) {
        return ($.isBoolean(bl) ? Boolean(bl) : false);
    };

    /**
     *
     * 我的 Ajax。
     *
     */
    $.myAjax = function (options) {
        // DOM ID，载入 HTML 片段的 DOM
        options.id = ($.isBlank(options.id) ? "#main-content-inner" : ("#" + options.id));
        // 请求  Url
        options.url = ($.isBlank(options.url) ? (globalBasePath + "error/xxx.html") : (globalBasePath + options.url));
        // 请求方式
        options.type = ($.isBlank(options.type) ? "get" : options.type.toLowerCase());
        // 是否异步：true-是；false-否
        options.async = (($.type(options.async) === "boolean") ? options.async : true);
        // URL 是否路由：true-是；false-否
        options.route = (($.type(options.route) === "boolean") ? options.route : false);
        // 是否显示等待模态框，true-显示；false-不显示，默认：不显示
        options.modal = (($.type(options.modal) === "boolean") ? options.modal : false);
        // 返回数据的类型，默认为 json
        options.dataType = ($.isBlank(options.dataType) ? "json" : options.dataType.toLowerCase());
        // 加载信息
        options.loadMsg = ($.isBlank(options.loadMsg) ? "" : options.loadMsg);
        // 提交按钮
        options.submitBtn = ($.is_jQueryObj(options.submitBtn) ? options.submitBtn : null);
        // 提交按钮的信息
        options.submitMsg = ($.isBlank(options.submitMsg) ? "正在提交…" : (options.submitMsg + "…"));

        /*
         * 在数据类型为“html”的前提下，showHtml 的默认值为 true，数据类型为其他时，showHtml 的值为 false。
         * 1.true-立即显示 html；
         * 2.false-不立即显示 html。
         *
         */
        if (options.dataType === "html") {
            options.showHtml = (($.type(options.showHtml) === "boolean") ? options.showHtml : true);
        } else {
            options.showHtml = false;
        }

        // 请求参数
        // 请求参数为对象
        if ($.isObject(options.data)) {
            options.data._ = new Date().getTime();

            // 请求参数为数组
        } else if ($.isArray(options.data)) {
            options.data.push({
                name: "_",
                value: new Date().getTime()
            });

            // 请求参数为空
        } else {
            options.data = new Object();
            options.data._ = new Date().getTime();
        }

        // 提交按钮的名称
        var submitBtnName = "提交";

        var jqXhr = $.ajax({
            url: options.url,
            type: options.type,
            data: options.data,
            async: options.async,
            dataType: options.dataType,
            beforeSend: function (xhr) { // 请求之前
                // 显示等待模态框
                $.showLoadModal({
                    modal: options.modal,
                    loadMsg: options.loadMsg
                });

                if ($.is_jQueryObj(options.submitBtn)) {
                    submitBtnName = options.submitBtn.html();

                    // 禁用提交按钮
                    options.submitBtn.html("<i class='fa fa-spinner fa-spin'></i>" + options.submitMsg).attr({"disabled": "disabled"});
                }

                if ($.isFunction(options.beforeSendFn)) {
                    options.beforeSendFn(xhr);
                }
            },
            complete: function (xhr, textStatus) { // 请求完成
                // 隐藏等待模态框
                $.showLoadModal({
                    modal: false
                });

                if ($.is_jQueryObj(options.submitBtn)) {
                    // 启用提交按钮
                    options.submitBtn.html(submitBtnName).removeAttr("disabled");
                }

                if ($.isFunction(options.completeFn)) {
                    options.completeFn(xhr, textStatus);
                }
            },
            success: function (data, textStatus, jqXhr) { // 请求成功
                // 如果返回数据的类型为：json
                if (options.dataType === "json") {
                    if (data.resultCode === 0) {
                        if ($.isFunction(options.successFn)) {
                            options.successFn(data, textStatus, jqXhr);
                        }
                    } else {
                        $.toast({
                            top: 5,
                            msg: data.resultMsg,
                            type: "error",
                            close: 6000
                        });

                        if ($.isFunction(options.successErrorFn)) {
                            options.successErrorFn(data, textStatus, jqXhr);
                        }
                    }

                    // 如果返回数据的类型为：html
                } else if (options.dataType === "html") {
                    if ($.isObject(data)) {
                        if (data.resultCode != 0) {
                            $.toast({
                                top: 5,
                                msg: data.resultMsg,
                                type: "error",
                                close: 6000
                            });
                        }
                    } else {
                        if (options.showHtml) {
                            $(options.id).html(data);
                        }
                    }

                    if ($.isFunction(options.successFn)) {
                        options.successFn(data, textStatus, jqXhr);
                    }

                    // 如果返回数据的类型为：其他
                } else {
                    if ($.isFunction(options.successFn)) {
                        options.successFn(data, textStatus, jqXhr);
                    }
                }
            },
            error: function (xhr, textStatus, errorThrown) { // 请求失败
                if ($.isFunction(options.errorFn)) {
                    options.errorFn(xhr, textStatus, errorThrown);
                } else {
                    // 获取状态码
                    var statusCode = xhr.status;
                    // 服务器返回的字符串
                    var responseText = xhr.responseText;

                    // 登录超时
                    if (statusCode === 401) {
                        $.toast({
                            top: 5,
                            msg: "您已登录超时，请重新登录",
                            type: "error",
                            close: 6000
                        });

                        // 无访问权限
                    } else if (statusCode === 403) {
                        $.toast({
                            top: 5,
                            msg: "您无访问权限，请联系管理授权",
                            type: "error",
                            close: 6000
                        });

                        // 请求参数不合法
                    } else if (statusCode === 412) {
                        $.toast({
                            top: 5,
                            msg: "您的请求参数不合法--->" + responseText,
                            type: "error",
                            close: 6000
                        });

                        // 访问的页面不存在
                    } else if (statusCode === 404) {
                        $.toast({
                            top: 5,
                            msg: "您访问的页面不存在",
                            type: "error",
                            close: 6000
                        });

                        // 服务器内部错误
                    } else if (statusCode === 500) {
                        $.toast({
                            top: 5,
                            msg: "系统繁忙，请稍候再试",
                            type: "error",
                            close: 6000
                        });

                        // 其他
                    } else {
                        $.toast({
                            top: 5,
                            msg: "网络连接失败，请稍候再试",
                            type: "error",
                            close: 6000
                        });
                    }
                }
            }
        });

        return jqXhr;
    };

    /**
     *
     * 我的 Load Ajax。
     *
     */
    $.fn.myLoad = function (options) {
        // 请求  Url
        options.url = ($.isBlank(options.url) ? (globalBasePath + "error/xxx.html") : (globalBasePath + options.url));
        // 请求参数，默认使用 GET 方式-传递附加参数时自动转换为 POST 方式
        options.data = ($.isObject(options.data) ? options.data : null);
        // 是否显示等待模态框，true-显示；false-不显示，默认：不显示
        options.modal = (($.type(options.modal) === "boolean") ? options.modal : false);
        // 加载信息
        options.loadMsg = ($.isBlank(options.loadMsg) ? "" : options.loadMsg);

        // 当前对象
        var $this = this;

        // 显示等待模态框
        $.showLoadModal({
            modal: options.modal,
            loadMsg: options.loadMsg
        });

        $this.load(
            options.url,
            options.data,
            function (data) {
                // 隐藏等待模态框
                $.showLoadModal({
                    modal: false
                });

                if ($.isFunction(options.successFn)) {
                    options.successFn($this, data);
                }
            }
        );
    };
})(jQuery);